

#include "Node.ih"
#include "DumpObjectTree.h"
#include <iostream>
#include "DumpObjectTree.h"
#include "Controller.h"

NodeLeaf::NodeLeaf()
: Node(QString("leaf"), 0) {
    // set up a new editPoint and adjust its size and set the focus to it.
    editPoint = new MathEditPoint(this);
    editPoint->adjustSize();
    // Make sure we have only one child node (editPoint) for this
    Q_ASSERT_X(children().size() == 1, "NodeLeaf::NodeLeaf",
            "Should only have one child that is a MathEditPoint.");
    // reset the size policy and size for this
    setSizePolicy(editPoint->sizePolicy());
    setFocusPolicy(Qt::StrongFocus);
    setFocusProxy(editPoint);
    editPoint->show();
}

NodeLeaf::NodeLeaf(QString& content)
: Node(QString("leaf"), 0) {
    // set up a new editPoint and adjust its size and set the focus to it.
    editPoint = new MathEditPoint(this);
    editPoint->setText(content);
    // Make sure we have only one child node (editPoint) for this
    Q_ASSERT_X(children().size() == 1, "NodeLeaf::NodeLeaf",
            "Should only have one child that is a MathEditPoint.");
    // reset the size policy and size for this
    setSizePolicy(editPoint->sizePolicy());
    setFocusPolicy(Qt::StrongFocus);
    setFocusProxy(editPoint);
    editPoint->show();
}

QString NodeLeaf::toCasString() const {
    Q_ASSERT_X(children().size() == 1, "NodeLeaf::toCasString",
            "Should only have one child that is a MathEditPoint.");
    // the following has to do with the number of children that can be set
    // not the number it has.
    Q_ASSERT_X(numChildren() == 0, "NodeLeaf::toCasString",
            "Should only have one child that is a MathEditPoint.");
    return editPoint->text();
}

QString NodeLeaf::toPrintString() const {
    return toCasString();
}

QString NodeLeaf::toParseString() const {
    return toCasString();
}

int NodeLeaf::getInputPosition(bool& found) const {
    if (hasFocus()) {
        found = true;
        return editPoint->cursorPosition();
    } else {
        return editPoint->text().size();
    }
}

void NodeLeaf::setInputPosition(int& position) {
    // input cursor is placed on zero
    // if the cursor is placed on zero and that is the right hand
    // side of a edit point then zero is passed to next node
    // and that node can place it in first position if possible.
    // otherwise it will just stay at end of preveus input position.

    // if it falls in this leaf
    if (position - editPoint->text().size() <= 0) {
        setFocus();
        editPoint->setCursorPosition(position);
        position = position - editPoint->text().size();
    } else {
        Q_ASSERT_X(position > editPoint->text().size(), "",
                "The input position should be outside of this leaf.");
        position = position - editPoint->text().size();
    }
}

bool NodeLeaf::isConstant() const {
    // TODO check if it is a known id
    return editPoint->isNumber();
}

QSize NodeLeaf::sizeHint() const {
    return editPoint->sizeHint();
}

void NodeLeaf::keyPressEvent(QKeyEvent *event) {

    if (event->key() == Qt::Key_Enter or event->key() == Qt::Key_Return) {
        event->accept();
        if (event->modifiers() == Qt::ShiftModifier) {
            qDebug("enter with shift.");
            // TOOD add solve approximate here
        }
        // have to handle this enter for solve here
        // because it needs to know what branch to replace with solution
        Node* parentNode = qobject_cast<Node*>(parentWidget());

        Q_ASSERT_X(parentNode != 0 and parentNode != nullptr, "", "Patent is not a node.");
        Q_ASSERT_X(getController() != 0 and getController() != nullptr, "",
                "Unable to access controller form Node.");

        if (getNodeType() == "empty" and parentNode->getNodeType() == "equal") {
            clearFocus();
            getController()->getSolution(getTopNode(), this);
        }
    } else {
        // all other keys will get passed up to parent
        event->ignore();
    }

}

QString NodeLeaf::getNodeType() const {
    // should not be both a number and an identifier
    Q_ASSERT_X((editPoint->isNumber() xor editPoint->isIdentifier())
            or (!editPoint->isNumber() and !editPoint->isIdentifier()),
            "NodeLeaf::getNodeType", "Contradicting leaf type.");

    if (editPoint->isNumber())
        return QString("number");
    else if (editPoint->isIdentifier())
        return QString("identifier");
    else if (editPoint->text().size() == 0)
        return QString("empty");
    else
        return QString("unknown");
}

QString NodeLeaf::getNodeValue() const {
    return editPoint->text();
}



